#include "StdAfx.h"
#include "Log.h"

static const  LPTSTR szLogLevel[4] = {_T("Unknown"), _T("[Error]:"), _T("[Warning]:"), _T("[Info]:")};

CLog::CLog(void)
{
	m_level = LOG_UNKNOWN;
	m_szHead = NULL;
	m_szBody = NULL;
}

CLog::~CLog(void)
{
	if (m_szHead)
	{
		delete m_szHead;
	}

	if (m_szBody)
	{
		delete m_szBody;
	}
}

CLog::CLog(LPTSTR szHead, UINT nHeadLen, LOG_LEVEL level, LPTSTR szBody, UINT nBodyLen)
{
	m_szHead = NULL;
	m_szBody = NULL;

	ASSERT(szHead != NULL);
	ASSERT(szBody != NULL);

	if(szHead && szBody && (level > LOG_UNKNOWN && level <= LOG_INFO))
	{
		if (m_szHead == NULL && m_szBody == NULL)
		{
			m_szHead = new TCHAR[MAX_HEAD_SIZE];
			m_szBody = new TCHAR[MAX_BODY_SIZE];

			if(m_szHead && m_szBody)
			{
				lstrcpyn(m_szHead, szHead, MAX_HEAD_SIZE);
				lstrcpyn(m_szBody, szBody, MAX_BODY_SIZE);
				m_level = level;
			}
		}
	}
}

void CLog::GetLogInfo(LPTSTR info, UINT nMaxLen)
{
	ASSERT(info);

	if (info)
	{
		CString out = CString(m_szHead) + CString(szLogLevel[m_level]) + CString(m_szBody);
		lstrcpyn(info, out, nMaxLen);
	}
}

CLog& CLog::operator=(const CLog& log)
{
	m_level = log.m_level;
	if(m_szHead == NULL)
	{
		m_szHead = new TCHAR[MAX_HEAD_SIZE];
	}
	lstrcpy(m_szHead, log.m_szHead);

	if(m_szBody == NULL)
	{
		m_szBody = new TCHAR[MAX_BODY_SIZE];
	}
	lstrcpy(m_szBody, log.m_szBody);

	return *this;
}




CLogNode::CLogNode(void)
{
	m_pNext = NULL;
}

CLogNode::~CLogNode(void)
{
}

CLogNode::CLogNode(CLog& log)
{
	m_log = log;
	m_pNext = NULL;
}


CLogFile::CLogFile(void)
{
	m_pHead = NULL;
	m_nNodeCount = 0;
	m_hFile = NULL;
	m_bSave = FALSE;
	m_szLogBuffer = NULL;
	m_bBufUpdated = FALSE;

	m_szLogBuffer = new TCHAR[MAX_NODE*(MAX_HEAD_SIZE+MAX_LEVEL_SIZE+MAX_BODY_SIZE+1)];
	ASSERT(m_szLogBuffer);
}

CLogFile::CLogFile(LPCTSTR lpszFileName)
{
	CLogFile::CLogFile();

	if( lpszFileName )
	{
		CFileException e;
		m_hFile = new CFile;
		if (!m_hFile->Open(lpszFileName, CFile::modeCreate|CFile::modeReadWrite|CFile::shareDenyNone|CFile::typeText, &e))
		{
			delete m_hFile;
			return;
		}
	}	
}

CLogFile::~CLogFile(void)
{
	if (m_pHead)
	{
		CLogNode* pNode = m_pHead;
		while(pNode)
		{
			CLogNode* pRelease = pNode;
			pNode = pNode->m_pNext;
			delete pRelease;
		}
	}
	m_nNodeCount = 0;

	if (m_hFile)
	{
		m_hFile->Close();
		delete m_hFile;
	}

	if(m_szLogBuffer)
	{
		delete[] m_szLogBuffer;
	}
}

BOOL CLogFile::AddLogNode(CLogNode *pAddNode)
{
	BOOL bRet = FALSE;
	CLogNode* pNode = m_pHead;

	m_mutex.Lock();

	if (pNode == NULL)
	{
		m_pHead = pAddNode;
		pNode = pAddNode;
	}
	else
	{	
		while(pNode->m_pNext)
		{
			pNode = pNode->m_pNext;
		}
		pNode->m_pNext = pAddNode;		
	}
	if(m_nNodeCount <= MAX_NODE)
	{		
		m_nNodeCount++;
	}
	else
	{
		pNode = m_pHead;
		m_pHead = m_pHead->m_pNext;
		delete pNode;
	}

	m_bBufUpdated = TRUE;

	m_mutex.Unlock();

	if(m_bSave)
	{
		LogOut(pAddNode);
	}

	return bRet;
}

BOOL CLogFile::LogOut(CLogNode* pNode)
{
	BOOL bRet = FALSE;

	if (m_hFile && pNode)
	{
		TCHAR szText[512] = {0};
		pNode->m_log.GetLogInfo(szText, 512);
		
		m_hFile->Write(szText, lstrlen(szText)*2);
		bRet = TRUE;
	}

	return bRet;
}

BOOL CLogFile::SetLogFilePath(LPCTSTR lpszPath)
{
	BOOL bRet = FALSE;
	CFileException e;

	if(lpszPath)
	{
		if(m_hFile)
		{
			m_hFile->Close();
		}
		else
		{
			m_hFile = new CFile;			
		}

		if( !m_hFile->Open(lpszPath, CFile::modeCreate|CFile::modeReadWrite|CFile::shareDenyNone, &e))
		{
			delete m_hFile;
			bRet = FALSE;
		}
		else
		{
			bRet = TRUE;
		}
	}

	return bRet;
}

void CLogFile::EnableLog(void)
{
	if (m_hFile)
	{
		m_bSave = TRUE;
	}
}

void CLogFile::DisableLog(void)
{
	if (m_hFile)
	{
		m_bSave = FALSE;
	}
}

LPTSTR CLogFile::GetLogBuffer(BOOL &bUpdated)
{
	m_mutex.Lock();
	bUpdated = m_bBufUpdated;

	if (m_bBufUpdated && m_szLogBuffer)
	{
		CLogNode* pNode = m_pHead;
		UINT nPosition = 0;
		TCHAR szNode[512] = {0};

		while(pNode)
		{
			pNode->m_log.GetLogInfo(szNode, sizeof(szNode)/2);
			//UINT nLength =wcslen(szNode);
			wcscpy_s(m_szLogBuffer+nPosition, wcslen(szNode)+1, szNode);
			nPosition += wcslen(szNode);

			pNode = pNode->m_pNext;
		}
	}

	m_bBufUpdated = FALSE;
	m_mutex.Unlock();

	return m_szLogBuffer;
}


